<!-- author: xuett -->
<!-- date: 2023-01-12 10:34:25 -->
<!-- description: 排序Table -->
<template>
  <G-dialog v-model:dialogshow="dialogVisible" width="50%" title="排序">
    <template #content>
      <div class="sort-container">
        <div class="sort-btn-box">
          <el-button icon="Top" @click="sortOperation('', 1)">上移</el-button>
          <el-button icon="Bottom" @click="sortOperation('', 2)">下移</el-button>
          <el-button type="primary" icon="Upload" plain @click="sortOperation('', 3)">置顶</el-button>
          <el-button type="primary" icon="Download" plain @click="sortOperation('', 4)">置底</el-button>
        </div>
        <div class="sort-table">
          <el-table v-if="refreshTable" ref="sortTableRef" class="sortTable" :tree-props="{ hasChildren: 'hasChildren' }" stripe :data="tableData" border>
            <el-table-column type="selection" width="55" align="center" />
            <el-table-column prop="originIndex" label="序号" width="55" align="center"></el-table-column>
            <el-table-column v-for="item in tableHeader" :key="item.originIndex" :prop="item.prop" :label="item.label" align="center" show-overflow-tooltip>
            </el-table-column>
            <el-table-column label="操作" align="center" width="400" fixed="right">
              <template #default="scope">
                <div class="sort-operation">
                  <el-button v-if="scope.$index > 0" icon="Top" @click="sortOperation(scope.$index, 5)">上移</el-button>
                  <el-button v-if="scope.$index < tableData.length - 1" icon="Bottom" @click="sortOperation(scope.$index, 6)">下移</el-button>
                  <el-button v-if="scope.$index > 0" type="primary" plain icon="Upload" @click="sortOperation(scope.$index, 7)">置顶</el-button>
                  <el-button v-if="scope.$index < tableData.length - 1" plain type="primary" icon="Download" @click="sortOperation(scope.$index, 8)">
                    置底
                  </el-button>
                </div>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </div>
    </template>
    <template #footer>
      <el-button type="primary" @click="onSubmit">保存</el-button>
      <el-button @click="handleClose">取消</el-button>
    </template>
  </G-dialog>
</template>

<script setup>
import { useLayoutStore } from "@/store/layout";
import { ElMessage } from "element-plus";

const $layoutStore = useLayoutStore();

const $props = defineProps({
  sortTable: {
    type: Object,
    default: () => {
      return { tableData: [], tableHeader: [] };
    }
  }
});
const $emit = defineEmits(["updateTable"]);
//监听传入table变化
watch(
  () => $props.sortTable,
  (newVal) => {
    state.tableData = JSON.parse(JSON.stringify(newVal.tableData));
    state.tableData.forEach((item, index) => {
      item.originIndex = index + 1;
      item.currentIndex = index;
    });
    state.tableHeader = newVal.tableHeader;
  }
);
watch(
  () => $layoutStore.sortDialogshow,
  (newVal) => {
    if (newVal) {
      nextTick(() => {
        initSort("sortTable");
      });
    }
  }
);

const dialogVisible = computed({
  get: () => $layoutStore.sortDialogshow,
  set: (val) => ($layoutStore.sortDialogshow = val)
});

const sortTableRef = ref(null);
const state = reactive({
  tableData: [],
  tableHeader: [],
  selectRow: [],
  refreshTable: true //重新渲染表格状态
});
const { tableData, tableHeader, refreshTable } = toRefs(state);

//排序
const sortOperation = (index, type) => {
  state.selectRow = sortTableRef.value.getSelectionRows();
  let table = state.tableData;
  //排序勾选项
  if (type < 5) {
    if (!state.selectRow.length) {
      ElMessage({
        message: "请至少勾选一条数据",
        type: "warning"
      });
    } else {
      //先对勾选内容排序
      let list = state.selectRow.sort((a, b) => {
        return a.currentIndex - b.currentIndex;
      });
      //反转数组
      let reversalList = [];
      list.forEach((item) => {
        reversalList.unshift(item);
      });
      if (type == 1) {
        //上移
        let disableList = [];
        list.map((item) => {
          //索引为0或前一个同是勾选项，则不能上移
          if (item.currentIndex == 0 || disableList.includes(item.currentIndex - 1)) {
            disableList.push(item.currentIndex);
          } else {
            disableList.push(item.currentIndex - 1);
            [table[item.currentIndex - 1], table[item.currentIndex]] = [table[item.currentIndex], table[item.currentIndex - 1]];
          }
        });
      } else if (type == 2) {
        //下移
        let disableList = [],
          lastIndex = table.length - 1;
        reversalList.map((item) => {
          //索引为最后一个或后一个同是勾选项，则不能下移
          if (item.currentIndex == lastIndex || disableList.includes(item.currentIndex + 1)) {
            disableList.push(item.currentIndex);
          } else {
            disableList.push(item.currentIndex + 1);
            [table[item.currentIndex + 1], table[item.currentIndex]] = [table[item.currentIndex], table[item.currentIndex + 1]];
          }
        });
      } else if (type == 3 || type == 4) {
        //3:置顶, 4:置底
        //按索引从大到小删除
        reversalList.map((item) => {
          table.splice(item.currentIndex, 1);
          return;
        });
        if (type == 3) {
          //按索引从大到小加入table
          reversalList.forEach((item) => {
            table.unshift(item);
          });
        } else {
          //按索引从小到大加入table
          list.forEach((item) => {
            table.push(item);
          });
        }
      }
      //重置当前排序值currentIndex
      table.forEach((item, index) => {
        item.currentIndex = index;
      });
    }
  } else if (type == 5) {
    //上移,和上一个替换
    table[index].currentIndex--;
    table[index - 1].currentIndex++;
    [table[index - 1], table[index]] = [table[index], table[index - 1]];
  } else if (type == 6) {
    //下移，和下一个替换
    table[index].currentIndex++;
    table[index + 1].currentIndex--;
    [table[index], table[index + 1]] = [table[index + 1], table[index]];
  } else if (type == 7 || type == 8) {
    //7:置顶 unshift, 8:置底 push
    let row = table[index];
    table.splice(index, 1);
    type == 7 ? table.unshift(row) : table.push(row);
    table.forEach((item, index) => {
      item.currentIndex = index;
    });
  }
};

// 创建拖拽实例
var sortF = null;
const initSort = (className) => {
  const table = document.querySelector(`.${className} .el-table__body-wrapper tbody`);
  if (table) {
    // eslint-disable-next-line no-undef
    sortF = new Sortable(table, {
      group: "shared",
      animation: 150, //单位：ms，定义排序动画的时间
      easing: "cubic-bezier(1, 0, 0, 1)", //动画
      onStart: () => {
        console.log("开始拖动");
      },
      // 结束拖动事件
      onEnd: ({ newIndex, oldIndex }) => {
        console.log(`拖动前索引${oldIndex}---拖动后索引${newIndex}`, "结束拖动");
        handleTable(oldIndex, newIndex);
      }
    });
  }
};

//每次排序完，销毁实例，刷新table
const handleTable = (oldIndex, newIndex) => {
  state.refreshTable = false;
  sortF.destroy();
  sortF = null;
  const currRow = state.tableData.splice(oldIndex, 1)[0];
  state.tableData.splice(newIndex, 0, currRow);
  //重置当前排序值currentIndex
  state.tableData.forEach((item, index) => {
    item.currentIndex = index;
  });
  nextTick(() => {
    state.refreshTable = true;
    setTimeout(() => {
      initSort("sortTable");
    }, 200);
  });
};

//保存
const onSubmit = () => {
  $emit("updateTable", state.tableData);
  $layoutStore.sortDialogshow = false;
};

//取消
const handleClose = () => {
  $layoutStore.sortDialogshow = false;
};
</script>

<style scoped lang="scss">
.sort-container {
  width: 100%;
  .sort-btn-box {
    width: 100%;
    margin-bottom: 20px;
  }
  .sort-table {
    width: 100%;
    .sort-operation {
      // display: flex;
      // flex-wrap: nowrap;
      .el-button {
        padding: 7px 8px;
      }
    }
  }
}

//隐藏table全选
:deep(.el-table th.el-table__cell:nth-child(1) .cell) {
  visibility: hidden;
}
</style>
